home *** CD-ROM | disk | FTP | other *** search
/ AMIGA-CD 2 / Amiga-CD - Volume 2.iso / gepackte_disketten / 1994 / 08_94_5.dms / 08_94_5.adf / term-4.0-Source.lha / termSaveWindow.c < prev    next >
C/C++ Source or Header  |  1994-06-30  |  19KB  |  930 lines

  1. /*
  2. **    termSaveWindow.c
  3. **
  4. **    Support routines for saving IFF-ILBM files
  5. **
  6. **    Copyright © 1990-1994 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* Current compression mode. */
  13.  
  14. #define DUMP        0
  15. #define RUN        1
  16.  
  17.     /* ByteRun compression data. */
  18.  
  19. #define MINRUN        3
  20. #define MAXRUN        128
  21. #define MAXDAT        128
  22.  
  23.     /* Chunk types. */
  24.  
  25. #define ID_ILBM        MAKE_ID('I','L','B','M')
  26. #define ID_ANNO        MAKE_ID('A','N','N','O')
  27. #define ID_BMHD        MAKE_ID('B','M','H','D')
  28. #define ID_CMAP        MAKE_ID('C','M','A','P')
  29. #define ID_CAMG        MAKE_ID('C','A','M','G')
  30. #define ID_BODY        MAKE_ID('B','O','D','Y')
  31.  
  32.     /* Masking technique. */
  33.  
  34. #define mskNone        0
  35.  
  36.     /* Compression techniques. */
  37.  
  38. #define cmpNone        0
  39. #define cmpByteRun1    1
  40.  
  41.     /* A bitmap header. */
  42.  
  43. typedef struct
  44. {
  45.     UWORD        w,h;            /* raster width & height in pixels */
  46.     WORD        x,y;            /* position for this image */
  47.     UBYTE        nPlanes;        /* # source bitplanes */
  48.     UBYTE        masking;        /* masking technique */
  49.     UBYTE        compression;        /* compression algorithm */
  50.     UBYTE        pad1;            /* UNUSED.  For consistency, put 0 here.*/
  51.     UWORD        transparentColor;    /* transparent "color number" */
  52.     UBYTE        xAspect,yAspect;    /* aspect ratio, a rational number x/y */
  53.     WORD        pageWidth,pageHeight;    /* source "page" size in pixels */
  54. } BitMapHeader;
  55.  
  56.     /* A single 8-bit colour register. */
  57.  
  58. typedef struct
  59. {
  60.     UBYTE        red,            /* red component, 0..255 */
  61.             green,            /* green component, 0..255 */
  62.             blue;            /* blue component, 0..255 */
  63. } ColorRegister;
  64.  
  65.     /* Local packer data. */
  66.  
  67. STATIC LONG        PackedBytes;
  68. STATIC BYTE        Buffer[MAXDAT + 1];
  69.  
  70.     /* PutDump(register PLANEPTR Destination,register LONG Count):
  71.      *
  72.      *    Output a byte dump.
  73.      */
  74.  
  75. STATIC PLANEPTR __regargs
  76. PutDump(register PLANEPTR Destination,register LONG Count)
  77. {
  78.     register PLANEPTR Source = Buffer;
  79.  
  80.     *Destination++     = Count - 1;
  81.      PackedBytes    += Count + 1;
  82.  
  83.     while(Count--)
  84.         *Destination++ = *Source++;
  85.  
  86.     return(Destination);
  87. }
  88.  
  89.     /* PutRun(register PLANEPTR Destination,LONG Count,WORD Char):
  90.      *
  91.      *    Output a byte run.
  92.      */
  93.  
  94. STATIC PLANEPTR __regargs
  95. PutRun(register PLANEPTR Destination,LONG Count,WORD Char)
  96. {
  97.     *Destination++     = -(Count - 1);
  98.     *Destination++     = Char;
  99.      PackedBytes    += 2;
  100.  
  101.     return(Destination);
  102. }
  103.  
  104.     /* PackRow(PLANEPTR *SourcePtr,register PLANEPTR Destination,LONG RowSize):
  105.      *
  106.      *    Pack a row of bitmap data using ByteRun compression,
  107.      *    based on the original "EA IFF 85" pack.c example code.
  108.      */
  109.  
  110. STATIC LONG __regargs
  111. PackRow(PLANEPTR *SourcePtr,register PLANEPTR Destination,LONG RowSize)
  112. {
  113.     register PLANEPTR Source = *SourcePtr;
  114.  
  115.     WORD    Buffered    = 1,
  116.         RunStart    = 0;
  117.     BYTE    Mode        = DUMP,
  118.         LastChar,
  119.         Char;
  120.  
  121.     PackedBytes = 0;
  122.  
  123.     Buffer[0] = LastChar = Char = *Source++;
  124.  
  125.     RowSize--;
  126.  
  127.     while(RowSize--)
  128.     {
  129.         Buffer[Buffered++] = Char = *Source++;
  130.  
  131.         if(Mode)
  132.         {
  133.             if((Char != LastChar) || (Buffered - RunStart > MAXRUN))
  134.             {
  135.                 Destination    = PutRun(Destination,Buffered - 1 - RunStart,LastChar);
  136.                 Buffer[0]    = Char;
  137.                 Buffered    = 1;
  138.                 RunStart    = 0;
  139.                 Mode        = DUMP;
  140.             }
  141.         }
  142.         else
  143.         {
  144.             if(Buffered > MAXDAT)
  145.             {
  146.                 Destination    = PutDump(Destination,Buffered - 1);
  147.                 Buffer[0]    = Char;
  148.                 Buffered    = 1;
  149.                 RunStart    = 0;
  150.             }
  151.             else
  152.             {
  153.                 if(Char == LastChar)
  154.                 {
  155.                     if(Buffered - RunStart >= MINRUN)
  156.                     {
  157.                         if(RunStart)
  158.                             Destination = PutDump(Destination,RunStart);
  159.  
  160.                         Mode = RUN;
  161.                     }
  162.                     else
  163.                     {
  164.                         if(!RunStart)
  165.                             Mode = RUN;
  166.                     }
  167.                 }
  168.                 else
  169.                     RunStart = Buffered - 1;
  170.             }
  171.         }
  172.  
  173.         LastChar = Char;
  174.     }
  175.  
  176.     if(Mode)
  177.         PutRun(Destination,Buffered - RunStart,LastChar);
  178.     else
  179.         PutDump(Destination,Buffered);
  180.  
  181.     *SourcePtr = Source;
  182.  
  183.     return(PackedBytes);
  184. }
  185.  
  186.     /* PutANNO(struct IFFHandle *Handle):
  187.      *
  188.      *    Output `ANNO' chunk.
  189.      */
  190.  
  191. STATIC BYTE __regargs
  192. PutANNO(struct IFFHandle *Handle)
  193. {
  194.     extern    UBYTE __far    VersTag[];
  195.         WORD        Len;
  196.  
  197.     LONG    Error;
  198.  
  199.     Len = strlen(&VersTag[1]);
  200.  
  201.         /* Push the `ANNO' chunk on the stack. */
  202.  
  203.     if(!(Error = PushChunk(Handle,0,ID_ANNO,Len)))
  204.     {
  205.             /* Write the creator string. */
  206.  
  207.         if(WriteChunkBytes(Handle,&VersTag[1],Len) == Len)
  208.         {
  209.                 /* Pop the `ANNO' chunk. */
  210.  
  211.             if(!(Error = PopChunk(Handle)))
  212.                 return(TRUE);
  213.         }
  214.         else
  215.             Error = IoErr();
  216.     }
  217.  
  218.     SetIoErr(Error);
  219.  
  220.     return(FALSE);
  221. }
  222.  
  223.     /* PutBMHD():
  224.      *
  225.      *    Output `BMHD' chunk.
  226.      */
  227.  
  228. STATIC BYTE __regargs
  229. PutBMHD(struct IFFHandle *Handle,struct Window *Window,UBYTE Compression,LONG Left,LONG Top,LONG Width,LONG Height)
  230. {
  231.     struct DisplayInfo    DisplayInfo;
  232.     LONG            Error = 0;
  233.  
  234.         /* Get the display aspect ratio. */
  235.  
  236.     if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,GetVPModeID(&Window -> WScreen -> ViewPort)))
  237.     {
  238.         BitMapHeader Header;
  239.  
  240.             /* Fill in the bitmap header. */
  241.  
  242.         Header . w            = Width;
  243.         Header . h            = Height;
  244.         Header . pageWidth        = Window -> WScreen -> Width;
  245.         Header . pageHeight        = Window -> WScreen -> Height;
  246.         Header . x            = Left;
  247.         Header . y            = Top;
  248.         Header . nPlanes        = Window -> WScreen -> RastPort . BitMap -> Depth;
  249.         Header . masking        = mskNone;
  250.         Header . compression        = Compression;
  251.         Header . pad1            = 0;
  252.         Header . transparentColor    = 0;
  253.         Header . xAspect        = DisplayInfo . Resolution . x;
  254.         Header . yAspect        = DisplayInfo . Resolution . y;
  255.  
  256.             /* Push the `BMHD' chunk on the stack. */
  257.  
  258.         if(!(Error = PushChunk(Handle,0,ID_BMHD,sizeof(BitMapHeader))))
  259.         {
  260.                 /* Write the bitmap header. */
  261.  
  262.             if(WriteChunkBytes(Handle,&Header,sizeof(BitMapHeader)) == sizeof(BitMapHeader))
  263.             {
  264.                     /* Pop the `BMHD' chunk. */
  265.  
  266.                 if(!(Error = PopChunk(Handle)))
  267.                     return(TRUE);
  268.             }
  269.             else
  270.                 Error = IoErr();
  271.         }
  272.     }
  273.     else
  274.         Error = ERR_NO_MEM;
  275.  
  276.     if(Error)
  277.         SetIoErr(Error);
  278.  
  279.     return(FALSE);
  280. }
  281.  
  282.     /* PutCMAP(struct IFFHandle *Handle,struct ViewPort *VPort):
  283.      *
  284.      *    Output `CMAP' chunk, only 4-bit colour registers
  285.      *    are supported so far.
  286.      */
  287.  
  288. STATIC BYTE __regargs
  289. PutCMAP(struct IFFHandle *Handle,struct ViewPort *VPort)
  290. {
  291.     LONG Error;
  292.  
  293.         /* Push the `CMAP' chunk on the stack. */
  294.  
  295.     if(!(Error = PushChunk(Handle,0,ID_CMAP,3 * VPort -> ColorMap -> Count)))
  296.     {
  297.         ColorRegister    Colour;
  298.         LONG        i;
  299.         ULONG        Value,
  300.                 R,G,B;
  301.  
  302.             /* Read and convert all the
  303.              * ColorMap entries (4 bit colour
  304.              * components only).
  305.              */
  306.  
  307.         if(Kick30)
  308.         {
  309.             ULONG RGB[3];
  310.  
  311.             for(i = 0 ; i < VPort -> ColorMap -> Count ; i++)
  312.             {
  313.                     /* Read colour value. */
  314.     
  315.                 GetRGB32(VPort -> ColorMap,i,1,RGB);
  316.     
  317.                     /* Store the colour components. */
  318.     
  319.                 Colour . red    = RGB[0] >> 24;
  320.                 Colour . green    = RGB[1] >> 24;
  321.                 Colour . blue    = RGB[2] >> 24;
  322.     
  323.                     /* Write the colours. */
  324.     
  325.                 if(WriteChunkBytes(Handle,&Colour,3) != 3)
  326.                     return(FALSE);
  327.             }
  328.         }
  329.         else
  330.         {
  331.             for(i = 0 ; i < VPort -> ColorMap -> Count ; i++)
  332.             {
  333.                     /* Read colour value. */
  334.     
  335.                 Value = GetRGB4(VPort -> ColorMap,i);
  336.     
  337.                     /* Split the value into components. */
  338.     
  339.                 R = (Value >> 8) & 0xF;
  340.                 G = (Value >> 4) & 0xF;
  341.                 B = (Value     ) & 0xF;
  342.     
  343.                     /* Store the colour components. */
  344.     
  345.                 Colour . red    = (R << 4) | R;
  346.                 Colour . green    = (G << 4) | G;
  347.                 Colour . blue    = (B << 4) | B;
  348.     
  349.                     /* Write the colours. */
  350.     
  351.                 if(WriteChunkBytes(Handle,&Colour,3) != 3)
  352.                     return(FALSE);
  353.             }
  354.         }
  355.  
  356.             /* Pop the `CMAP' chunk. */
  357.  
  358.         if(!(Error = PopChunk(Handle)))
  359.             return(TRUE);
  360.     }
  361.  
  362.     SetIoErr(Error);
  363.  
  364.     return(FALSE);
  365. }
  366.  
  367.     /* PutCAMG(struct IFFHandle *Handle,struct ViewPort *VPort):
  368.      *
  369.      *    Output `CAMG' chunk.
  370.      */
  371.  
  372. STATIC BYTE __regargs
  373. PutCAMG(struct IFFHandle *Handle,struct ViewPort *VPort)
  374. {
  375.     LONG Error;
  376.  
  377.     if(!(Error = PushChunk(Handle,0,ID_CAMG,sizeof(ULONG))))
  378.     {
  379.         ULONG ViewModes = GetVPModeID(VPort);
  380.  
  381.         if(WriteChunkBytes(Handle,&ViewModes,sizeof(ULONG)) == sizeof(ULONG))
  382.         {
  383.             if(!(Error = PopChunk(Handle)))
  384.                 return(TRUE);
  385.         }
  386.         else
  387.             Error = IoErr();
  388.     }
  389.  
  390.     if(Error)
  391.         SetIoErr(Error);
  392.  
  393.     return(FALSE);
  394. }
  395.  
  396.     /* PutBODY(struct IFFHandle *Handle)
  397.      *
  398.      *    Output `BODY' chunk.
  399.      */
  400.  
  401. STATIC BYTE __regargs
  402. PutBODY(struct IFFHandle *Handle,struct BitMap *BitMap,UBYTE Compression)
  403. {
  404.     BYTE         Success = FALSE;
  405.     PLANEPTR    *Planes;
  406.     LONG         Error = 0;
  407.  
  408.         /* Allocate temporary bitplane pointers. */
  409.  
  410.     if(Planes = (PLANEPTR *)AllocVecPooled(BitMap -> Depth * sizeof(PLANEPTR *),MEMF_ANY | MEMF_CLEAR))
  411.     {
  412.         register LONG i;
  413.  
  414.             /* Copy the bitplane pointers. */
  415.  
  416.         for(i = 0 ; i < BitMap -> Depth ; i++)
  417.             Planes[i] = BitMap -> Planes[i];
  418.  
  419.             /* Are we to compress the data? */
  420.  
  421.         if(Compression == cmpByteRun1)
  422.         {
  423.             PLANEPTR PackBuffer;
  424.  
  425.                 /* Allocate line compression buffer. */
  426.  
  427.             if(PackBuffer = (PLANEPTR)AllocVecPooled(BitMap -> BytesPerRow * 2,MEMF_ANY))
  428.             {
  429.                     /* Push the `BODY' chunk on the stack. */
  430.  
  431.                 if(!(Error = PushChunk(Handle,0,ID_BODY,IFFSIZE_UNKNOWN)))
  432.                 {
  433.                     register LONG    PackedBytes,
  434.                             j;
  435.  
  436.                         /* So far, we are quite successful,
  437.                          * any write access to fail will
  438.                          * cause `Success' to drop to FALSE.
  439.                          */
  440.  
  441.                     Success = TRUE;
  442.  
  443.                         /* Compress all the rows. */
  444.  
  445.                     for(i = 0 ; Success && i < BitMap -> Rows ; i++)
  446.                     {
  447.                             /* Compress all the planes. */
  448.  
  449.                         for(j = 0 ; Success && j < BitMap -> Depth ; j++)
  450.                         {
  451.                                 /* Do the compression. */
  452.  
  453.                             PackedBytes = PackRow(&Planes[j],PackBuffer,BitMap -> BytesPerRow);
  454.  
  455.                                 /* Write the compressed data. */
  456.  
  457.                             if(WriteChunkBytes(Handle,PackBuffer,PackedBytes) != PackedBytes)
  458.                             {
  459.                                 Error = IoErr();
  460.  
  461.                                 Success = FALSE;
  462.                             }
  463.                         }
  464.                     }
  465.  
  466.                         /* Pop the `BODY' chunk. */
  467.  
  468.                     if(Success)
  469.                     {
  470.                         if(Error = PopChunk(Handle))
  471.                             Success = FALSE;
  472.                     }
  473.                 }
  474.  
  475.                     /* Free the line compression buffer. */
  476.  
  477.                 FreeVecPooled(PackBuffer);
  478.             }
  479.             else
  480.                 Error = ERR_NO_MEM;
  481.         }
  482.         else
  483.         {
  484.                 /* Push the `BODY' chunk on the stack. */
  485.  
  486.             if(!(Error = PushChunk(Handle,0,ID_BODY,IFFSIZE_UNKNOWN)))
  487.             {
  488.                 register LONG j;
  489.  
  490.                     /* So far, we are quite successful,
  491.                      * any write access to fail will
  492.                      * cause `Success' to drop to FALSE.
  493.                      */
  494.  
  495.                 Success = TRUE;
  496.  
  497.                     /* Compress all the rows. */
  498.  
  499.                 for(i = 0 ; Success && i < BitMap -> Rows ; i++)
  500.                 {
  501.                         /* Compress all the planes. */
  502.  
  503.                     for(j = 0 ; Success && j < BitMap -> Depth ; j++)
  504.                     {
  505.                             /* Write the row. */
  506.  
  507.                         if(WriteChunkBytes(Handle,Planes[j],BitMap -> BytesPerRow) != BitMap -> BytesPerRow)
  508.                         {
  509.                             Error = IoErr();
  510.  
  511.                             Success = FALSE;
  512.                         }
  513.                         else
  514.                             Planes[j] += BitMap -> BytesPerRow;
  515.                     }
  516.                 }
  517.  
  518.                     /* Pop the `BODY' chunk. */
  519.  
  520.                 if(Success)
  521.                 {
  522.                     if(Error = PopChunk(Handle))
  523.                         Success = FALSE;
  524.                 }
  525.             }
  526.         }
  527.  
  528.             /* Free the temporary bitplane pointers. */
  529.  
  530.         FreeVecPooled(Planes);
  531.     }
  532.     else
  533.         Error = ERR_NO_MEM;
  534.  
  535.     if(Error)
  536.         SetIoErr(Error);
  537.  
  538.         /* Return the result. */
  539.  
  540.     return(Success);
  541. }
  542.  
  543.     /* SaveWindow(STRPTR Name,struct Window *Window):
  544.      *
  545.      *    Save the contents of a window to a file.
  546.      */
  547.  
  548. BYTE __regargs
  549. SaveWindow(STRPTR Name,struct Window *Window)
  550. {
  551.     BYTE    Success    = FALSE,
  552.         NewFile    = FALSE,
  553.         Locked    = TRUE;
  554.     LONG    Error    = 0;
  555.  
  556.     LockLayerRom(Window -> RPort -> Layer);
  557.  
  558.         // Datatypes available?
  559.  
  560.     if(DataTypesBase)
  561.     {
  562.         struct BitMap    *BitMap;
  563.         struct Screen    *Screen = Window -> WScreen;
  564.         LONG         Left,Top,
  565.                  Width,Height;
  566.         Object        *Picture = NULL;
  567.  
  568.             // Keep these handy
  569.  
  570.         Left    = Window -> LeftEdge    + Window -> BorderLeft;
  571.         Top    = Window -> TopEdge    + Window -> BorderTop;
  572.         Width    = Window -> Width    - (Window -> BorderLeft + Window -> BorderRight);
  573.         Height    = Window -> Height    - (Window -> BorderTop + Window -> BorderBottom);
  574.  
  575.             // This is where the window contents will go
  576.  
  577.         if(BitMap = AllocBitMap(Width,Height,GetBitMapAttr(Window -> RPort -> BitMap,BMA_DEPTH),NULL,Window -> RPort -> BitMap))
  578.         {
  579.             struct RastPort __aligned    RPort;
  580.             LONG                NumColours;
  581.  
  582.                 // Provide temporary storage
  583.  
  584.             InitRastPort(&RPort);
  585.  
  586.             RPort . BitMap = BitMap;
  587.  
  588.                 // Copy the window contents
  589.  
  590.             ClipBlit(Window -> RPort,Window -> BorderLeft,Window -> BorderTop,&RPort,0,0,Width,Height,MINTERM_COPY);
  591.  
  592.                 // Release the layer
  593.  
  594.             UnlockLayerRom(Window -> RPort -> Layer);
  595.  
  596.             Locked = FALSE;
  597.  
  598.                 // Wait until all data is transferred
  599.  
  600.             WaitBlit();
  601.  
  602.                 // Get the number of colours available on this screen
  603.  
  604.             NumColours = Screen -> ViewPort . ColorMap -> Count;
  605.  
  606.                 // Create a picture object
  607.  
  608.             if(Picture = NewDTObject("term image",
  609.                 DTA_SourceType,    DTST_RAM,
  610.                 DTA_GroupID,    GID_PICTURE,
  611.                 PDTA_NumColors,    NumColours,
  612.                 PDTA_BitMap,    BitMap,
  613.                 PDTA_ModeID,    GetVPModeID(&Screen -> ViewPort),
  614.             TAG_DONE))
  615.             {
  616.                 struct ColorRegister    *ColourMap;
  617.                 struct BitMapHeader    *BitMapHeader;
  618.                 ULONG            *Colours;
  619.  
  620.                     // Get the internal data arrays
  621.  
  622.                 if(GetDTAttrs(Picture,
  623.                     PDTA_BitMapHeader,    &BitMapHeader,
  624.                     PDTA_ColorRegisters,    &ColourMap,
  625.                     PDTA_CRegs,        &Colours,
  626.                 TAG_DONE) == 3)
  627.                 {
  628.                     LONG i;
  629.  
  630.                         // Fill in the bitmap header
  631.  
  632.                     BitMapHeader -> bmh_Left    = Left;
  633.                     BitMapHeader -> bmh_Top        = Top;
  634.                     BitMapHeader -> bmh_Width    = Width;
  635.                     BitMapHeader -> bmh_Height    = Height;
  636.                     BitMapHeader -> bmh_Depth    = GetBitMapAttr(BitMap,BMA_DEPTH);
  637.                     BitMapHeader -> bmh_PageWidth    = Screen -> Width;
  638.                     BitMapHeader -> bmh_PageHeight    = Screen -> Height;
  639.  
  640.                         // Get the 32 colours
  641.  
  642.                     GetRGB32(Screen -> ViewPort . ColorMap,0,NumColours,Colours);
  643.  
  644.                         // Get the 24 bit colours
  645.  
  646.                     for(i = 0 ; i < NumColours ; i++)
  647.                     {
  648.                         ColourMap[i] . red    = (UBYTE)(Colours[i * 3 + 0] >> 24);
  649.                         ColourMap[i] . green    = (UBYTE)(Colours[i * 3 + 1] >> 24);
  650.                         ColourMap[i] . blue    = (UBYTE)(Colours[i * 3 + 2] >> 24);
  651.                     }
  652.                 }
  653.                 else
  654.                 {
  655.                     Error = IoErr();
  656.  
  657.                     DisposeDTObject(Picture);
  658.  
  659.                     Picture = NULL;
  660.                 }
  661.             }
  662.             else
  663.                 Error = IoErr();
  664.         }
  665.         else
  666.             Error = ERROR_NO_FREE_STORE;
  667.  
  668.             // Successful so far?
  669.  
  670.         if(Picture)
  671.         {
  672.             BPTR FileHandle;
  673.  
  674.                 // Open the output file
  675.  
  676.             if(FileHandle = Open(Name,MODE_NEWFILE))
  677.             {
  678.                     // Save the image
  679.  
  680.                 if(DoMethod(Picture,DTM_WRITE,NULL,FileHandle,DTWM_IFF,NULL))
  681.                     Success = TRUE;
  682.                 else
  683.                 {
  684.                     Error = IoErr();
  685.  
  686.                     NewFile = TRUE;
  687.                 }
  688.  
  689.                 Close(FileHandle);
  690.             }
  691.             else
  692.                 Error = IoErr();
  693.  
  694.             DisposeDTObject(Picture);
  695.         }
  696.         else
  697.         {
  698.             if(BitMap)
  699.                 FreeBitMap(BitMap);
  700.         }
  701.     }
  702.     else
  703.     {
  704.         struct RastPort    *RPort;
  705.  
  706.             /* Allocate a dummy rastport, we will need only
  707.              * to copy the contents of the window into the
  708.              * bitmap.
  709.              */
  710.  
  711.         if(RPort = (struct RastPort *)AllocVecPooled(sizeof(struct RastPort),MEMF_ANY))
  712.         {
  713.             struct BitMap *BitMap;
  714.  
  715.                 /* Initialize the rastport with defaults. */
  716.  
  717.             InitRastPort(RPort);
  718.  
  719.                 /* Allocate a bitmap. */
  720.  
  721.             if(BitMap = (struct BitMap *)AllocVecPooled(sizeof(struct BitMap),MEMF_ANY))
  722.             {
  723.                 LONG    Width    = Window -> Width    - (Window -> BorderLeft + Window -> BorderRight),
  724.                     Height    = Window -> Height    - (Window -> BorderTop + Window -> BorderBottom),
  725.                     Left    = Window -> LeftEdge    + Window -> BorderLeft,
  726.                     Top    = Window -> TopEdge    + Window -> BorderTop;
  727.                 WORD    i;
  728.  
  729.                     /* Put it into the rastport. */
  730.  
  731.                 RPort -> BitMap = BitMap;
  732.  
  733.                     /* Initialize it with the window dimensions. */
  734.  
  735.                 InitBitMap(BitMap,Window -> WScreen -> RastPort . BitMap -> Depth,Width,Height);
  736.  
  737.                     /* Flag success so any allocation
  738.                      * to fail in the bitplane allocation
  739.                      * loop will indicate failure.
  740.                      */
  741.  
  742.                 Success = TRUE;
  743.  
  744.                     /* Allocate all the bitplanes necessary. */
  745.  
  746.                 for(i = 0 ; Success && i < BitMap -> Depth ; i++)
  747.                 {
  748.                     if(!(BitMap -> Planes[i] = AllocRaster(Width,Height)))
  749.                         Success = FALSE;
  750.                 }
  751.  
  752.                     /* Did we get all the planes we wanted? */
  753.  
  754.                 if(Success)
  755.                 {
  756.                     struct IFFHandle *Handle;
  757.  
  758.                         /* Copy the window contents to the
  759.                          * local bitmap.
  760.                          */
  761.  
  762.                     ClipBlit(Window -> RPort,Window -> BorderLeft,Window -> BorderTop,RPort,0,0,Width,Height,MINTERM_COPY);
  763.  
  764.                         /* Release the lock on the window layer. */
  765.  
  766.                     UnlockLayerRom(Window -> RPort -> Layer);
  767.  
  768.                         /* Wait for the data to arrive. */
  769.  
  770.                     WaitBlit();
  771.  
  772.                     Locked = FALSE;
  773.  
  774.                         /* Reset the success indicator. */
  775.  
  776.                     Success = FALSE;
  777.  
  778.                         /* Allocate an iff handle. */
  779.  
  780.                     if(Handle = AllocIFF())
  781.                     {
  782.                             /* Open a file for write access. */
  783.  
  784.                         if(Handle -> iff_Stream = Open(Name,MODE_NEWFILE))
  785.                         {
  786.                                 /* Remember that we succeeded
  787.                                  * in creating a new file.
  788.                                  */
  789.  
  790.                             NewFile = TRUE;
  791.  
  792.                                 /* Tell iffparse.library that it's
  793.                                  * a plain AmigaDOS file handle.
  794.                                  */
  795.  
  796.                             InitIFFasDOS(Handle);
  797.  
  798.                                 /* Open the file for writing. */
  799.  
  800.                             if(!(Error = OpenIFF(Handle,IFFF_WRITE)))
  801.                             {
  802.                                     /* Push parent chunk on the
  803.                                      * stack.
  804.                                      */
  805.  
  806.                                 if(!(Error = PushChunk(Handle,ID_ILBM,ID_FORM,IFFSIZE_UNKNOWN)))
  807.                                 {
  808.                                         /* Output all the chunk data. */
  809.  
  810.                                     if(PutANNO(Handle))
  811.                                     {
  812.                                         UBYTE Compression;
  813.  
  814.                                             /* Don't compress the bitmap if
  815.                                              * isn't really worth it.
  816.                                              */
  817.  
  818.                                         if(BitMap -> BytesPerRow > 4)
  819.                                             Compression = cmpByteRun1;
  820.                                         else
  821.                                             Compression = cmpNone;
  822.  
  823.                                         if(PutBMHD(Handle,Window,Compression,Left,Top,Width,Height))
  824.                                         {
  825.                                             if(PutCMAP(Handle,&Window -> WScreen -> ViewPort))
  826.                                             {
  827.                                                 if(PutCAMG(Handle,&Window -> WScreen -> ViewPort))
  828.                                                 {
  829.                                                     if(PutBODY(Handle,BitMap,Compression))
  830.                                                     {
  831.                                                             /* Pop the parent chunk
  832.                                                              * from the stack.
  833.                                                              */
  834.  
  835.                                                         if(!(Error = PopChunk(Handle)))
  836.                                                             Success = TRUE;
  837.                                                     }
  838.                                                     else
  839.                                                         Error = IoErr();
  840.                                                 }
  841.                                                 else
  842.                                                     Error = IoErr();
  843.                                             }
  844.                                             else
  845.                                                 Error = IoErr();
  846.                                         }
  847.                                         else
  848.                                             Error = IoErr();
  849.                                     }
  850.                                     else
  851.                                         Error = IoErr();
  852.                                 }
  853.  
  854.                                     /* Close the iff handle. */
  855.  
  856.                                 CloseIFF(Handle);
  857.                             }
  858.  
  859.                                 /* Close the file. */
  860.  
  861.                             if(!Close(Handle -> iff_Stream))
  862.                             {
  863.                                 Error = IoErr();
  864.  
  865.                                 Success = FALSE;
  866.                             }
  867.                         }
  868.                         else
  869.                             Error = IoErr();
  870.  
  871.                             /* Free the iff handle. */
  872.  
  873.                         FreeIFF(Handle);
  874.                     }
  875.                     else
  876.                         Error = ERR_NO_MEM;
  877.                 }
  878.                 else
  879.                     Error = ERR_NO_MEM;
  880.  
  881.                     /* Free all bitplanes. */
  882.  
  883.                 for(i = 0 ; i < BitMap -> Depth ; i++)
  884.                 {
  885.                     if(BitMap -> Planes[i])
  886.                         FreeRaster(BitMap -> Planes[i],Width,Height);
  887.                 }
  888.  
  889.                     /* Free the bitmap. */
  890.  
  891.                 FreeVecPooled(BitMap);
  892.             }
  893.             else
  894.                 Error = ERR_NO_MEM;
  895.  
  896.                 /* Free the rastport. */
  897.  
  898.             FreeVecPooled(RPort);
  899.         }
  900.         else
  901.             Error = ERR_NO_MEM;
  902.     }
  903.  
  904.         /* Release the window layer in case it is still locked. */
  905.  
  906.     if(Locked)
  907.         UnlockLayerRom(Window -> RPort -> Layer);
  908.  
  909.         /* If successful, clear the `executable' bit. */
  910.  
  911.     if(Success)
  912.     {
  913.         AddProtection(Name,FIBF_EXECUTE);
  914.  
  915.         if(Config -> MiscConfig -> CreateIcons)
  916.             AddIcon(CaptureName,FILETYPE_PICTURE,TRUE);
  917.     }
  918.     else
  919.     {
  920.             /* Delete the remains of the file. */
  921.  
  922.         if(NewFile)
  923.             DeleteFile(Name);
  924.     }
  925.  
  926.         /* Return the result. */
  927.  
  928.     return(Success);
  929. }
  930.